/* *
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */
'use strict';
import H from '../../parts/Globals.js';
import U from '../../parts/Utilities.js';

var merge = U.merge;
var Annotation = H.Annotation, CrookedLine = Annotation.types.crookedLine, ControlPoint = Annotation.ControlPoint,
    MockPoint = Annotation.MockPoint;

/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * @private
 */
function getSecondCoordinate(p1, p2, x) {
    return (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x) + p1.y;
}

var Tunnel = function () {
    CrookedLine.apply(this, arguments);
};
H.extendAnnotation(Tunnel, CrookedLine, {
        getPointsOptions: function () {
            var pointsOptions = CrookedLine.prototype.getPointsOptions.call(this);
            pointsOptions[2] = this.heightPointOptions(pointsOptions[1]);
            pointsOptions[3] = this.heightPointOptions(pointsOptions[0]);
            return pointsOptions;
        },
        getControlPointsOptions: function () {
            return this.getPointsOptions().slice(0, 2);
        },
        heightPointOptions: function (pointOptions) {
            var heightPointOptions = merge(pointOptions);
            heightPointOptions.y += this.options.typeOptions.height;
            return heightPointOptions;
        },
        addControlPoints: function () {
            CrookedLine.prototype.addControlPoints.call(this);
            var options = this.options,
                controlPoint = new ControlPoint(this.chart, this, merge(options.controlPointOptions, options.typeOptions.heightControlPoint), 2);
            this.controlPoints.push(controlPoint);
            options.typeOptions.heightControlPoint = controlPoint.options;
        },
        addShapes: function () {
            this.addLine();
            this.addBackground();
        },
        addLine: function () {
            var line = this.initShape(merge(this.options.typeOptions.line, {
                type: 'path',
                points: [
                    this.points[0],
                    this.points[1],
                    function (target) {
                        var pointOptions = MockPoint.pointToOptions(target.annotation.points[2]);
                        pointOptions.command = 'M';
                        return pointOptions;
                    },
                    this.points[3]
                ]
            }), false);
            this.options.typeOptions.line = line.options;
        },
        addBackground: function () {
            var background = this.initShape(merge(this.options.typeOptions.background, {
                type: 'path',
                points: this.points.slice()
            }));
            this.options.typeOptions.background = background.options;
        },
        /**
         * Translate start or end ("left" or "right") side of the tunnel.
         * @private
         * @param {number} dx - the amount of x translation
         * @param {number} dy - the amount of y translation
         * @param {boolean} [end] - whether to translate start or end side
         */
        translateSide: function (dx, dy, end) {
            var topIndex = Number(end), bottomIndex = topIndex === 0 ? 3 : 2;
            this.translatePoint(dx, dy, topIndex);
            this.translatePoint(dx, dy, bottomIndex);
        },
        /**
         * Translate height of the tunnel.
         * @private
         * @param {number} dh - the amount of height translation
         */
        translateHeight: function (dh) {
            this.translatePoint(0, dh, 2);
            this.translatePoint(0, dh, 3);
            this.options.typeOptions.height = this.points[3].y - this.points[0].y;
        }
    },
    /**
     * A tunnel annotation.
     *
     * @extends annotations.crookedLine
     * @sample highcharts/annotations-advanced/tunnel/
     *         Tunnel
     * @product highstock
     * @optionparent annotations.tunnel
     */
    {
        typeOptions: {
            xAxis: 0,
            yAxis: 0,
            /**
             * Background options.
             *
             * @type {Object}
             * @excluding height, point, points, r, type, width, markerEnd,
             *            markerStart
             */
            background: {
                fill: 'rgba(130, 170, 255, 0.4)',
                strokeWidth: 0
            },
            line: {
                strokeWidth: 1
            },
            /**
             * The height of the annotation in terms of yAxis.
             */
            height: -2,
            /**
             * Options for the control point which controls
             * the annotation's height.
             *
             * @extends annotations.crookedLine.controlPointOptions
             * @excluding positioner, events
             */
            heightControlPoint: {
                positioner: function (target) {
                    var startXY = MockPoint.pointToPixels(target.points[2]),
                        endXY = MockPoint.pointToPixels(target.points[3]), x = (startXY.x + endXY.x) / 2;
                    return {
                        x: x - this.graphic.width / 2,
                        y: getSecondCoordinate(startXY, endXY, x) -
                            this.graphic.height / 2
                    };
                },
                events: {
                    drag: function (e, target) {
                        if (target.chart.isInsidePlot(e.chartX - target.chart.plotLeft, e.chartY - target.chart.plotTop)) {
                            target.translateHeight(this.mouseMoveToTranslation(e).y);
                            target.redraw(false);
                        }
                    }
                }
            }
        },
        /**
         * @extends annotations.crookedLine.controlPointOptions
         * @excluding positioner, events
         */
        controlPointOptions: {
            events: {
                drag: function (e, target) {
                    if (target.chart.isInsidePlot(e.chartX - target.chart.plotLeft, e.chartY - target.chart.plotTop)) {
                        var translation = this.mouseMoveToTranslation(e);
                        target.translateSide(translation.x, translation.y, this.index);
                        target.redraw(false);
                    }
                }
            }
        }
    });
Annotation.types.tunnel = Tunnel;
export default Tunnel;
